package zzps.exeed.web.handle;

import zzps.exeed.kernel.holder.MethodHolder;
import zzps.exeed.kernel.holder.PandaHolder;
import zzps.exeed.kernel.holder.ParameterHolder;
import zzps.exeed.kernel.tool.ClassTool;
import zzps.exeed.kernel.tool.ReflectTool;
import zzps.exeed.web.Context;
import zzps.exeed.web.handle.argument.HandlerMethodArgumentResolver;
import zzps.exeed.kernel.holder.ModelAttribute;
import zzps.exeed.web.http.HttpMethod;
import zzps.exeed.web.transformer.InputOutputTransformerManager;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Parameter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class Action implements Handler{

    private PandaHolder pandaHolder;
    private MethodHolder methodHolder;
    private String path;
    private HttpMethod[] httpMethods;
    private Map<ParameterHolder, HandlerMethodArgumentResolver> argumentResolverCache;
    public Action(PandaHolder pandaHolder, MethodHolder methodHolder) {
        this.pandaHolder = pandaHolder;
        this.methodHolder = methodHolder;
        argumentResolverCache = new ConcurrentHashMap<>(methodHolder.getParameters().length * 2);
        init();
    }
    private void init(){
        List<HandlerMethodArgumentResolver> resolvers = HandlerManager.get().getArgumentResolvers();
        ParameterHolder[] parameters = methodHolder.getParameters();
        for (ParameterHolder parameterHolder : parameters) {
            Class<?> aClass = parameterHolder.getType();
            if (!ClassTool.isSimpleType(aClass)&&!aClass.isInterface()){
                Constructor<?> constructor = ReflectTool.getConstructor(aClass);
                HashMap<String, Field> hashMap = new HashMap<>(32);
                ReflectTool.getNormalField(aClass,hashMap,true);
                List<Field> list = hashMap.values().stream().toList();
                ModelAttribute modelAttribute = new ModelAttribute(constructor, list);
                parameterHolder.setModelAttribute(modelAttribute);
            }
            boolean support = false;
            for (HandlerMethodArgumentResolver resolver : resolvers) {
                if (resolver.support(parameterHolder)){
                    support = true;
                    argumentResolverCache.put(parameterHolder,resolver);
                    break;
                }
            }
            if (!support){
                throw new RuntimeException("参数没有匹配的处理器");
            }
        }
    }

    @Override
    public void handle(Context context) throws Throwable {
        ParameterHolder[] parameters = methodHolder.getParameters();
        Object[] paramObjects = new Object[parameters.length];
        for (int i = 0; i < parameters.length; i++) {
            ParameterHolder parameter = parameters[i];
            HandlerMethodArgumentResolver argumentResolver = argumentResolverCache.get(parameter);
            paramObjects[i] = argumentResolver.resolveArgument(parameter,context);
//            Class<?> type = parameter.getType();
//            if (Context.class.isAssignableFrom(type)) {
//                paramObjects[i] = context;
//            }else if (type.isInstance(context.request())){
//                paramObjects[i] = context.request();
//            }else if (type.isInstance(context.response())){
//                paramObjects[i] = context.response();
//            }
//            else{
//                Class<?> aClass = parameter.getType();
//            }
        }
        Object result = methodHolder.invoke(pandaHolder.get(), paramObjects);
//        InputOutputTransformerManager.get().json().output(result,context);
        context.output(result);
    }
}
